package com.zcn.io.web.auth.filter;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zcn.io.common.exception.ServiceException;
import com.zcn.io.common.pojo.CommonResult;
import com.zcn.io.web.auth.utils.JwtUtils;
import com.zcn.io.web.auth.LoginUser;
import com.zcn.io.web.service.CacheService;
import io.jsonwebtoken.Claims;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Objects;

import static com.zcn.io.web.auth.utils.AuthConstants.*;

/**
 * @desc:
 * @author: 202438 邱建伟
 * @date: 2024/10/20 14:18
 * @Copyright (c) 2024, zcn. All rights reserved.
 */
@Slf4j
@Component
@AllArgsConstructor
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    private final CacheService redisCache;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, ServletException, IOException {

        if (request.getRequestURI().contains("/auth/login")) {
            filterChain.doFilter(request, response);
            return;
        }

        String token = request.getHeader(AUTH_HEADER);
        if (StrUtil.isEmpty(token)) {
            filterChain.doFilter(request, response);
            return;
        }

        if (token.startsWith(TOKEN_PREFIX)) {
            token = token.replace(TOKEN_PREFIX, "");
        } else {
            filterChain.doFilter(request, response);
            return;
        }

        // 解析token
        String userid = "";
        try {
            Claims claims = JwtUtils.parseJWT(token);
            userid = claims.getSubject();
        } catch (Exception e) {
            log.error("token解析失败:{}", e.getMessage());
            e.printStackTrace();
            filterChain.doFilter(request, response);
            return;
//            handleError(response, HttpStatus.UNAUTHORIZED, CommonResult.error(401,"认证失败，请重新登录!"));
        }

        LoginUser longinUser = redisCache.getLoginUserFromCache(USER_LOGIN_CACHE_PREFIX + userid);
        if (Objects.nonNull(longinUser)) {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(longinUser, null, longinUser.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        filterChain.doFilter(request, response);
    }

    private final ObjectMapper objectMapper = new ObjectMapper();

    private void handleError(HttpServletResponse response, HttpStatus status, CommonResult<String> commonResult) throws IOException {
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setStatus(status.value());
        response.setCharacterEncoding("UTF-8");

        PrintWriter out = response.getWriter();

        out.print(objectMapper.writeValueAsString(commonResult));
        out.flush();
    }
}
